/*
The MIT License
Copyright (c) 2019 Lehrstuhl Informatik 11 - RWTH Aachen University
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE

This file is part of embeddedRTPS.

Author: i11 - Embedded Software, RWTH Aachen University
*/

#ifndef RTPS_STATEFULWRITER_H
#define RTPS_STATEFULWRITER_H

#include "rtps/entities/ReaderProxy.h"
#include "rtps/entities/Writer.h"
#include "rtps/storages/MemoryPool.h"
#include "rtps/storages/SimpleHistoryCache.h"

#define NetworkDriver struct rtps_UdpDriver
#define SimpleHistoryCache struct rtps_SimpleHistoryCache
#define CacheChange struct rtps_CacheChange
typedef struct rtps_StatefulWriter {
  struct rtps_Writer writer;
  sys_mutex_t m_mutex;
  ThreadPool *mp_threadPool/* = nullptr*/;

  rtps_PacketInfo m_packetInfo;
  NetworkDriver *m_transport;
  bool m_enforceUnicast;

  TopicKind_t m_topicKind/* = TopicKind_t::NO_KEY*/;
  SequenceNumber_t m_nextSequenceNumberToSend/* = {0, 1}*/;
  SimpleHistoryCache *m_history;
  sys_thread_t m_heartbeatThread;

  Count_t m_hbCount/*{1}*/;

  bool m_running/*{ = true*/;
  bool m_thread_running/*{ = false*/;

} StatefulWriterT;
#define StatefulWriter StatefulWriterT

void rtps_StatefulWriterT_construct();
void rtps_StatefulWriterT_destruct(struct rtps_StatefulWriter *sfw);

bool rtps_StatefulWriterT_init(struct rtps_StatefulWriter *sfw, TopicData attributes, TopicKind_t topicKind, ThreadPool *threadPool,
          NetworkDriver *driver, bool enfUnicast/* = false*/);

bool rtps_StatefulWriterT_addNewMatchedReader(struct rtps_StatefulWriter *sfw, const ReaderProxy *newProxy);
void rtps_StatefulWriterT_removeReader(struct rtps_StatefulWriter *sfw, const Guid_t *guid);
void rtps_StatefulWriterT_removeReaderOfParticipant(struct rtps_StatefulWriter *sfw, const GuidPrefix_t *guidPrefix);
//! Executes required steps like sending packets. Intended to be called by
//! worker threads
void rtps_StatefulWriterT_progress(struct rtps_StatefulWriter *sfw);
const CacheChange *rtps_StatefulWriterT_newChange(struct rtps_StatefulWriter *sfw, ChangeKind_t kind, const uint8_t *data, DataSize_t size);
void rtps_StatefulWriterT_setAllChangesToUnsent(struct rtps_StatefulWriter *sfw);
void rtps_StatefulWriterT_onNewAckNack(struct rtps_StatefulWriter *sfw, const SubmessageAckNack *msg,
                  const GuidPrefix_t *sourceGuidPrefix);
bool rtps_StatefulWriterT_sendData(struct rtps_StatefulWriter *sfw, const ReaderProxy *reader, const SequenceNumber_t *sn);
bool rtps_StatefulWriterT_sendDataWRMulticast(struct rtps_StatefulWriter *sfw, const ReaderProxy *reader,
                           const SequenceNumber_t *sn);
void rtps_StatefulWriterT_hbFunctionJumppad(void *thisPointer);
void rtps_StatefulWriterT_sendHeartBeatLoop(struct rtps_StatefulWriter *sfw);
void rtps_StatefulWriterT_sendHeartBeat(struct rtps_StatefulWriter *sfw);
bool rtps_StatefulWriterT_isIrrelevant(ChangeKind_t kind);
void rtps_StatefulWriterT_manageSendOptions();
void rtps_StatefulWriterT_resetSendOptions(struct rtps_StatefulWriter *sfw);

#define rtps_StatefulWriter_init rtps_StatefulWriterT_init

#define rtps_StatefulWriter_addNewMatchedReader rtps_StatefulWriterT_addNewMatchedReader
#define rtps_StatefulWriter_removeReader rtps_StatefulWriterT_removeReader
#define rtps_StatefulWriter_removeReaderOfParticipant rtps_StatefulWriterT_removeReaderOfParticipant
#define rtps_StatefulWriter_progress rtps_StatefulWriterT_progress
#define rtps_StatefulWriter_newChange rtps_StatefulWriterT_newChange
#define rtps_StatefulWriter_setAllChangesToUnsent rtps_StatefulWriterT_setAllChangesToUnsent
#define rtps_StatefulWriter_onNewAckNack rtps_StatefulWriterT_onNewAckNack
#define rtps_StatefulWriter_sendData rtps_StatefulWriterT_sendData
#define rtps_StatefulWriter_sendDataWRMulticast rtps_StatefulWriterT_sendDataWRMulticast
#define rtps_StatefulWriter_hbFunctionJumppad rtps_StatefulWriterT_hbFunctionJumppad
#define rtps_StatefulWriter_sendHeartBeatLoop rtps_StatefulWriterT_sendHeartBeatLoop
#define rtps_StatefulWriter_sendHeartBeat rtps_StatefulWriterT_sendHeartBeat
#define rtps_StatefulWriter_isIrrelevant rtps_StatefulWriterT_isIrrelevant
#define rtps_StatefulWriter_manageSendOptions rtps_StatefulWriterT_manageSendOptions
#define rtps_StatefulWriter_resetSendOptions rtps_StatefulWriterT_resetSendOptions

//using StatefulWriter = StatefulWriterT<UdpDriver>;

//#include "StatefulWriter.tpp"

#endif // RTPS_STATEFULWRITER_H
